多型的核心思想是「一個介面,多種實現」。允許同一個方法在不同的物件上有不同的表現形式,例如,當一個類別繼承另一個父類別,或是實現某個介面的時候,該類別可以重寫(Override)父類別或介面中的方法。
假設有一個父類別 Animal
,並且定義了 makeSound()
方法。
接著,有兩個子類別 Dog 和 Cat,它們各自重寫了 makeSound()
方法,分別返回 "Bark" 和 "Meow" 的聲音。即使我們使用 Animal
類別的參考變數來儲存 Dog 和 Cat 的物件,當呼叫 makeSound()
時,會根據物件的具體類型來執行相應的 makeSound()
實作。這種根據物件的真實類型來決定方法執行方式的機制就是多型的核心。
// 定義父類別 Animal
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
// 定義子類別 Dog 繼承自 Animal
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Bark");
}
}
// 定義子類別 Cat 繼承自 Animal
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow");
}
}
// 測試多型的範例
public class Main {
public static void main(String[] args) {
// 使用 Animal 類別的參考變數來儲存 Dog 和 Cat 的物件
Animal myDog = new Dog();
Animal myCat = new Cat();
// 呼叫 makeSound() 方法,根據物件的具體類型來執行相應的實作
myDog.makeSound(); // 輸出: Bark
myCat.makeSound(); // 輸出: Meow
}
}
多型的概念使得程式具備更大的彈性與擴展性,因為它允許開發者在不修改原有程式碼的情況下,新增新的類別或行為。透過多型,我們可以對不同類型的物件進行統一操作,而無需關心它們的具體類別,只需要關注它們是否實現了相同的介面或繼承了相同的父類別。
Java 中的多型主要透過方法重寫(Method Overriding)和介面實現(Interface Implementation)來達成。方法的選擇在執行時期決定,這就是所謂的「動態繫結」(Dynamic Binding),使程式的可讀性與維護性提高。同時,這也促進了SOLID中的「OCP(開放封閉原則)」,即軟體應該對擴展開放,對修改封閉,從而減少程式修改所帶來的潛在風險。